from flask import Flask, request, jsonify, abort
from functools import wraps
from admin_backend import update_user, get_all_users, get_single_user, renew_vip_service, query_user, \
    get_vip_packages, update_vip_package, delete_vip_package, create_admin, delete_admin, get_admins, update_admin, \
    delete_user, query_admin, get_image_by_id, get_images_by_admin
from config import Config
from models import db, User, Image, ImageVersion, UserCollect, CollectItem, UserAction, Admin, UserVIP, AdminAction
from datetime import datetime  # 必须导入datetime模块
import oss2
from datetime import datetime
import re
import jwt
from passlib.hash import argon2
from admin_backend import admin_required, get_all_images, upload_image, delete_image, update_image

app = Flask(__name__)
app.config.from_object(Config)
db.init_app(app)  # 初始化数据库连接

auth = oss2.Auth('LTAI5tSSsZreQros8dcchrTe', 'dKoToq83nsV1xMTJN9VwIiryzKOkhg')

# 全局设置响应头允许跨域
@app.after_request
def add_cors_headers(response):
    response.headers['Access-Control-Allow-Origin'] = '*'
    response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS'
    response.headers['Access-Control-Allow-Headers'] = 'Content-Type, X-User-ID'
    return response

# 北京region的正确配置（根据控制台显示的实际region配置）
endpoint = "https://oss-cn-beijing.aliyuncs.com"
bucketName = "mjseed-code-image"
bucket = oss2.Bucket(auth, endpoint, bucketName)

def validate_phone(phone):
    """验证中国大陆手机号格式（11位数字且以1开头）"""
    return re.match(r"^1[3-9]\d{9}$", phone) is not None

def generate_token(user_id):
    """生成JWT令牌"""
    return jwt.encode(
        {'user_id': user_id, 'exp': datetime.utcnow() + app.config['JWT_EXPIRATION']},
        app.config['SECRET_KEY'],
        algorithm='HS256'
    )

def token_required(f):
    """身份验证装饰器"""
    @wraps(f)
    def decorated(*args, **kwargs):
        if app.config['TESTING_MODE']:
            user_id = request.args.get('user_id')
            if not user_id:
                return jsonify({'error': '测试模式需要user_id参数'}), 401
            user = User.query.get(user_id)
            if not user:
                return jsonify({'error': '用户不存在'}), 404
            request.user = user
            return f(*args, **kwargs)
        
        token = request.headers.get('Authorization')
        if not token:
            return jsonify({'error': '缺少访问令牌'}), 401
        try:
            data = jwt.decode(token, app.config['SECRET_KEY'], algorithms=['HS256'])
            user = User.query.get(data['user_id'])
            if not user:
                raise ValueError('用户不存在')
            request.user = user
        except jwt.ExpiredSignatureError:
            return jsonify({'error': '令牌已过期'}), 401
        except Exception as e:
            return jsonify({'error': f'无效令牌: {str(e)}'}), 401
        return f(*args, **kwargs)
    return decorated

# ----------------- 路由定义 -----------------
#WPJ
@app.route('/register', methods=['POST'])
def register():
    """用户注册接口"""
    data = request.json
    required_fields = ['username', 'password', 'phone_number']
    for field in required_fields:
        if field not in data:
            return jsonify({'error': f'缺少必要字段: {field}'}), 400
    
    if not validate_phone(data['phone_number']):
        return jsonify({'error': '手机号格式无效'}), 400

    if User.query.filter_by(user_name=data['username']).first():
        return jsonify({'error': '用户名已被占用'}), 409
    if User.query.filter_by(phone_number=data['phone_number']).first():
        return jsonify({'error': '手机号已注册'}), 409

    try:
        new_user = User(
            user_name=data['username'],
            phone_number=data['phone_number'],
            membership_type='member'
        )
        new_user.set_password(data['password'])
        db.session.add(new_user)
        db.session.commit()
        return jsonify({
            'user_id': new_user.user_id,
            'username': new_user.user_name,
            'membership_type': new_user.membership_type
        }), 201
    except Exception as e:
        db.session.rollback()
        return jsonify({'error': f'注册失败: {str(e)}'}), 500

@app.route('/login', methods=['POST'])
def login():
    """用户登录接口"""
    data = request.json
    if 'username' not in data or 'password' not in data:
        return jsonify({'error': '需要用户名和密码'}), 400
    
    user = User.query.filter(
        (User.user_name == data['username']) |
        (User.phone_number == data['username'])
    ).first()
    
    if not user or not user.check_password(data['password']):
        return jsonify({'error': '用户名或密码错误'}), 401
    
    return jsonify({
        'user_id': user.user_id,
        'username': user.user_name,
        'token': generate_token(user.user_id)
    }), 200

# ----------------- 图片模块 -----------------
@app.route('/images/<string:image_id>', methods=['GET'])
def get_image_details(image_id):
    """通过image_id获取图片完整信息"""
    # 查询图片基本信息
    image = Image.query.get(image_id)
    if not image:
        return jsonify({'error': '图片不存在'}), 404

    # 查询所有版本信息（按上传时间倒序）
    versions = ImageVersion.query.filter_by(image_id=image_id)\
                    .order_by(ImageVersion.upload_at.desc()).all()

    # 查询关联评论及用户信息
    comments = db.session.query(
        UserAction.action_id,
        UserAction.comment_context,
        UserAction.create_at,
        User.user_id,
        User.user_name
    ).join(
        User, UserAction.user_id == User.user_id
    ).filter(
        UserAction.image_id == image_id,
        UserAction.action_type == 'comment'
    ).order_by(UserAction.create_at.desc()).all()

    # 构建响应数据结构
    response = {
        'basic_info': {
            'image_id': image.image_id,
            'title': image.image_title,
            'description': image.image_description,
            'resolution': image.resolution,
            'format': image.format,
            'tags': list(filter(None, [  # 过滤空标签
                image.image_tag1,
                image.image_tag2,
                image.image_tag3
            ])),
            'statistics': {
                'likes': image.beliked or 0,
                'collections': image.becollected or 0,
                'comments': image.comment_time or 0
            },
            'vip_exclusive': image.vip_exclusive
        },
        'versions': [{
            'version_id': v.version_id,
            'oss_path': f'https://mjseed-code-image.oss-cn-beijing.aliyuncs.com{mj_path}' 
                if (mj_path := v.oss_path.split('mjseed-code-image', 1)[-1]) 
                else v.oss_path,
            'status': v.audit_status,
            'upload_time': v.upload_at.isoformat(),
            'requires_vip': v.vip_exclusive
        } for v in versions],
        'comments': [{
            'id': c.action_id,
            'content': c.comment_context,
            'time': c.create_at.isoformat(),
            'author': {
                'user_id': c.user_id,
                'username': c.user_name
            }
        } for c in comments]
    }

    # 处理Midjourney代码（如果有）
    if image.midjourney_code:
        response['basic_info']['midjourney_code'] = image.midjourney_code
        response['basic_info']['code_copy_count'] = image.codecopy_time or 0

    return jsonify(response), 200

# ----------------- 收藏夹模块 -----------------
@app.route('/collect', methods=['POST', 'DELETE', 'GET', 'PATCH'])
@token_required
def manage_collection():
    user = request.user

    # ----------------- 创建操作（修改部分） -----------------
    if request.method == 'POST':
        data = request.json
        if not data:
            return jsonify({'error': '缺少请求体'}), 400
        
        # 分支1: 创建新收藏夹
        if 'collect_name' in data:
            if not data['collect_name'].strip():
                return jsonify({'error': '收藏夹名称不能为空'}), 400
            
            try:
                # 创建收藏夹
                new_collect = UserCollect(
                    user_id=user.user_id,
                    collect_name=data['collect_name'].strip()
                )
                db.session.add(new_collect)
                
                # 记录收藏夹创建行为
                action = UserAction(
                    user_id=user.user_id,
                    action_type='collect',
                    create_at=datetime.now()  # 自动记录时间
                )
                db.session.add(action)
                
                db.session.commit()
                return jsonify({
                    'collect_id': new_collect.usercollect_id,
                    'collect_name': new_collect.collect_name
                }), 201
            except Exception as e:
                db.session.rollback()
                return jsonify({'error': f'创建失败: {str(e)}'}), 500
        
        # 分支2: 添加收藏项
        elif all(k in data for k in ('usercollect_id', 'image_id', 'items_name')):
            collect = UserCollect.query.filter_by(
                usercollect_id=data['usercollect_id'],
                user_id=user.user_id
            ).first()
            if not collect:
                return jsonify({'error': '收藏夹不存在或无权访问'}), 404
            
            if not Image.query.get(data['image_id']):
                return jsonify({'error': '图片不存在'}), 404
            
            try:
                # 创建收藏项
                new_item = CollectItem(
                    usercollect_id=data['usercollect_id'],
                    image_id=data['image_id'],
                    items_name=data['items_name'].strip()
                )
                db.session.add(new_item)

                # 记录收藏项创建行为
                action = UserAction(
                    user_id=user.user_id,
                    action_type='collect_item',
                    image_id=data['image_id'],
                    create_at=datetime.now()
                )
                db.session.add(action)

                db.session.commit()
                return jsonify({
                    'item_id': new_item.items_id,
                    'image_id': new_item.image_id,
                    'item_name': new_item.items_name
                }), 201
            except Exception as e:
                db.session.rollback()
                return jsonify({'error': f'添加失败: {str(e)}'}), 500
        
        else:
            return jsonify({'error': '缺少必要参数'}), 400

    # ----------------- 查询操作 -----------------
    elif request.method == 'GET':
        try:
            # 获取收藏时间子查询
            collect_time_subq = db.session.query(
                UserAction.image_id,
                db.func.max(UserAction.create_at).label('collect_time')
            ).filter(
                UserAction.user_id == user.user_id,
                UserAction.action_type == 'collect'
            ).group_by(UserAction.image_id).subquery(name='collect_times')

            # 获取最新图片版本子查询
            latest_version_subq = db.session.query(
                ImageVersion.image_id,
                db.func.max(ImageVersion.upload_at).label('latest_upload')
            ).group_by(ImageVersion.image_id).subquery(name='latest_versions')

            # 主查询
            query = db.session.query(
                UserCollect.usercollect_id.label('collect_id'),
                UserCollect.collect_name,
                CollectItem.items_id,
                CollectItem.items_name,
                Image.image_id,
                Image.image_title,
                Image.image_description,
                Image.midjourney_code, 
                ImageVersion.oss_path,
                collect_time_subq.c.collect_time  
            ).outerjoin(
                CollectItem, 
                UserCollect.usercollect_id == CollectItem.usercollect_id
            ).outerjoin(
                Image, 
                CollectItem.image_id == Image.image_id
            ).outerjoin(
                latest_version_subq,
                Image.image_id == latest_version_subq.c.image_id
            ).outerjoin(
                ImageVersion,
                (ImageVersion.image_id == latest_version_subq.c.image_id) &
                (ImageVersion.upload_at == latest_version_subq.c.latest_upload)
            ).outerjoin(
                collect_time_subq,
                Image.image_id == collect_time_subq.c.image_id
            ).filter(
                UserCollect.user_id == user.user_id
            ).order_by(
                UserCollect.usercollect_id,
                CollectItem.items_id
            )

            results = query.all()
            
            # 结构化数据
            collections = {}
            for row in results:
                collect_id = row.collect_id
                
                if collect_id not in collections:
                    collections[collect_id] = {
                        'collect_id': collect_id,
                        'collect_name': row.collect_name,
                        'items': []
                    }
                
                if row.items_id:
                    item_data = {
                        'item_id': row.items_id,
                        'item_name': row.items_name,
                        'image': {
                            'image_id': row.image_id,
                            'title': row.image_title,
                            'description': row.image_description,
                            'midjourney_code': row.midjourney_code,  
                            'oss_path': f'https://mjseed-code-image.oss-cn-beijing.aliyuncs.com{mj_path}'
                                        if (mj_path := row.oss_path.split('mjseed-code-image', 1)[-1])
                                            else row.oss_path
                        },
                        'collect_time': row.collect_time.isoformat() if row.collect_time else None  
                    }
                    collections[collect_id]['items'].append(item_data)

            return jsonify(list(collections.values())), 200

        except Exception as e:
            app.logger.error(f"收藏查询失败: {str(e)}")
            return jsonify({'error': '获取收藏数据失败，请稍后重试'}), 500

    # ----------------- 删除操作 -----------------
    elif request.method == 'DELETE':
        # 获取删除目标和类型
        target_id = request.args.get('id')#是指items_id
        target_type = request.args.get('type')#type=item
        
        # 参数校验
        if not target_id or not target_type:
            return jsonify({'error': '需要items_id和type参数'}), 400
        
        # 分支1: 删除整个收藏夹
        if target_type == 'collect':
            # 验证收藏夹归属
            collect = UserCollect.query.filter_by(
                usercollect_id=target_id,
                user_id=user.user_id
            ).first()
            if not collect:
                return jsonify({'error': '收藏夹不存在或无权访问'}), 404
            
            try:
                # 先删除所有收藏项
                CollectItem.query.filter_by(usercollect_id=target_id).delete()
                # 再删除收藏夹
                db.session.delete(collect)
                db.session.commit()
                return jsonify({'message': '收藏夹及内容已删除'}), 200
            except Exception as e:
                db.session.rollback()
                return jsonify({'error': f'删除失败: {str(e)}'}), 500
        
        # 分支2: 删除单个收藏项
        elif target_type == 'item':
            # 获取收藏项并验证归属
            item = CollectItem.query.get(target_id)
            if not item:
                return jsonify({'error': '收藏项不存在'}), 404
            
            # 通过收藏夹验证用户权限
            collect = UserCollect.query.filter_by(
                usercollect_id=item.usercollect_id,
                user_id=user.user_id
            ).first()
            if not collect:
                return jsonify({'error': '无权操作此收藏项'}), 403
            
            try:
                db.session.delete(item)
                db.session.commit()
                return jsonify({'message': '收藏项已删除'}), 200
            except Exception as e:
                db.session.rollback()
                return jsonify({'error': f'删除失败: {str(e)}'}), 500
        
        else:
            return jsonify({'error': '无效操作类型'}), 400

    # ----------------- 查询操作 -----------------
    elif request.method == 'GET':
        try:
            # 步骤1: 获取每个图片的最新版本信息
            latest_version_subq = db.session.query(
                ImageVersion.image_id,
                db.func.max(ImageVersion.upload_at).label('latest_upload')
            ).group_by(ImageVersion.image_id).subquery(name='latest_versions')
            
            # 步骤2: 构建主查询
            query = db.session.query(
                UserCollect.usercollect_id.label('collect_id'),
                UserCollect.collect_name,
                CollectItem.items_id,
                CollectItem.items_name,
                Image.image_id,
                Image.image_title,
                Image.image_description,
                ImageVersion.oss_path
            ).outerjoin(  # 使用外连接保留空收藏夹
                CollectItem, 
                UserCollect.usercollect_id == CollectItem.usercollect_id
            ).outerjoin(  # 外连接处理可能已删除的图片
                Image, 
                CollectItem.image_id == Image.image_id
            ).outerjoin(  # 关联最新版本子查询
                latest_version_subq,
                Image.image_id == latest_version_subq.c.image_id
            ).outerjoin(  # 获取实际版本数据
                ImageVersion,
                (ImageVersion.image_id == latest_version_subq.c.image_id) &
                (ImageVersion.upload_at == latest_version_subq.c.latest_upload)
            ).filter(
                UserCollect.user_id == user.user_id
            ).order_by(
                UserCollect.usercollect_id,
                CollectItem.items_id
            )

            # 步骤3: 执行查询并处理结果
            results = query.all()
            
            # 步骤4: 结构化返回数据
            collections = {}
            for row in results:
                collect_id = row.collect_id
                
                # 初始化收藏夹结构
                if collect_id not in collections:
                    collections[collect_id] = {
                        'collect_id': collect_id,
                        'collect_name': row.collect_name,
                        'items': []
                    }
                
                # 处理收藏项（排除空记录）
                if row.items_id:
                    item_data = {
                        'item_id': row.items_id,
                        'item_name': row.items_name,
                        'image': {
                            'image_id': row.image_id,
                            'title': row.image_title,
                            'description': row.image_description,
                            'oss_path': row.oss_path
                        } if row.image_id else None  # 处理图片被删除的情况
                    }
                    collections[collect_id]['items'].append(item_data)

            return jsonify(list(collections.values())), 200

        except Exception as e:
            app.logger.error(f"收藏查询失败: {str(e)}")
            return jsonify({'error': '获取收藏数据失败，请稍后重试'}), 500
        
    # ----------------- 更新收藏夹，项名字 -----------------
    elif request.method == 'PATCH':
        data = request.json
        if not data:
            return jsonify({'error': '缺少请求体'}), 400

        # 参数验证
        required_fields = []
        if 'collect_id' in data and 'new_name' in data:
            # 分支1: 修改收藏夹名称
            collect = UserCollect.query.filter_by(
                usercollect_id=data['collect_id'],
                user_id=user.user_id
            ).first()
            
            if not collect:
                return jsonify({'error': '收藏夹不存在或无权操作'}), 404
            
            new_name = data['new_name'].strip()
            if not new_name:
                return jsonify({'error': '新名称不能为空'}), 400
            
            try:
                collect.collect_name = new_name
                db.session.commit()
                return jsonify({
                    'collect_id': collect.usercollect_id,
                    'new_name': collect.collect_name
                }), 200
            except Exception as e:
                db.session.rollback()
                return jsonify({'error': f'更新失败: {str(e)}'}), 500

        elif 'item_id' in data and 'new_name' in data:
            # 分支2: 修改收藏项名称
            item = CollectItem.query.get(data['item_id'])
            if not item:
                return jsonify({'error': '收藏项不存在'}), 404

            # 验证收藏夹归属
            collect = UserCollect.query.filter_by(
                usercollect_id=item.usercollect_id,
                user_id=user.user_id
            ).first()
            if not collect:
                return jsonify({'error': '无权操作此收藏项'}), 403
            
            new_name = data['new_name'].strip()
            if not new_name:
                return jsonify({'error': '新名称不能为空'}), 400
            
            try:
                item.items_name = new_name
                db.session.commit()
                return jsonify({
                    'item_id': item.items_id,
                    'new_name': item.items_name
                }), 200
            except Exception as e:
                db.session.rollback()
                return jsonify({'error': f'更新失败: {str(e)}'}), 500

        else:
            return jsonify({'error': '需要collect_id/new_name 或 item_id/new_name参数对'}), 400    

# ----------------- 评论模块--------------------------
@app.route('/comment', methods=['POST', 'GET', 'DELETE'])
@token_required
def comment_management():
    """
    评论管理接口
    POST: 发表评论（同步更新image_db评论次数）
    GET: 获取指定图片的评论列表
    DELETE: 删除评论（同步更新image_db评论次数）
    """
    user = request.user
    data = request.json if request.method == 'POST' else None

    # ----------------- 发表评论 -----------------
    if request.method == 'POST':
        # 参数校验
        if 'image_id' not in data or 'comment' not in data:
            return jsonify({'error': '需要image_id和comment参数'}), 400
        
        # 查询图片是否存在
        image = Image.query.get(data['image_id'])
        if not image:
            return jsonify({'error': '图片不存在'}), 404
        
        try:
            # 创建评论记录
            new_comment = UserAction(
                user_id=user.user_id,
                action_type='comment',
                image_id=data['image_id'],
                comment_context=data['comment'],
                create_at=datetime.now()
            )
            db.session.add(new_comment)

            
            # 初始化comment_time为0（如果字段为空）
            if image.comment_time is None:
                image.comment_time = 0
            # 评论次数加1（直接操作整数）
            image.comment_time += 1
            # -------------------------------------------

            db.session.add(image)
            db.session.commit()
            return jsonify({
                'comment_id': new_comment.action_id,
                'content': new_comment.comment_context
            }), 201
        except Exception as e:
            db.session.rollback()
            return jsonify({'error': str(e)}), 500

    # ----------------- 查询用户评论 -----------------
    elif request.method == 'GET':
        try:
            from sqlalchemy.orm import aliased

            # 获取当前用户所有评论及相关图片信息
            latest_version_subquery = db.session.query(
                ImageVersion.image_id,
                db.func.max(ImageVersion.upload_at).label('latest_upload_at')
            ).group_by(ImageVersion.image_id).subquery()

            latest_version = aliased(ImageVersion)

            comments = db.session.query(
                UserAction.action_id,
                UserAction.comment_context,
                UserAction.create_at,
                Image.image_id,
                Image.image_title,
                Image.image_description,
                latest_version.oss_path
            ).join(
                Image, UserAction.image_id == Image.image_id
            ).join(
                latest_version_subquery,
                Image.image_id == latest_version_subquery.c.image_id
            ).join(
                latest_version,
                (latest_version.image_id == latest_version_subquery.c.image_id) &
                (latest_version.upload_at == latest_version_subquery.c.latest_upload_at)
            ).filter(
                UserAction.user_id == request.user.user_id,
                UserAction.action_type == 'comment'
            ).order_by(UserAction.create_at.desc()).all()

            return jsonify([{
                'comment_id': c.action_id,
                'content': c.comment_context,
                'time': c.create_at.isoformat(),
                'image': {
                    'image_id': c.image_id,
                    'title': c.image_title,
                    'description': c.image_description,
                    'oss_path': f'https://mjseed-code-image.oss-cn-beijing.aliyuncs.com{mj_path}'
                                if (mj_path := c.oss_path.split('mjseed-code-image', 1)[-1])
                                     else c.oss_path
                }
            } for c in comments]), 200

        except Exception as e:
            return jsonify({'error': f'查询失败: {str(e)}'}), 500

    # ----------------- 用户删除评论 -----------------
    elif request.method == 'DELETE':
        # 前端传的comment_id实际对应action_id
        action_id = request.args.get('comment_id')  # 参数名保持comment_id不变
        if not action_id:
            return jsonify({'error': '需要评论ID'}), 400
    
        # 查询评论是否存在且用户有权操作
        comment = UserAction.query.filter_by(
            action_id=action_id,         # 数据库字段是action_id
            user_id=user.user_id,         # 验证所属用户
            action_type='comment'         # 确保是评论类型
        ).first()
    
        if not comment:
            return jsonify({'error': '评论不存在或无权操作'}), 404
    
        try:
            # 删除评论记录
            db.session.delete(comment)

            # 更新对应图片的评论次数
            image = Image.query.get(comment.image_id)
            if image and image.comment_time > 0:  # 确保次数不低于0
                image.comment_time -= 1
        
            db.session.add(image)
            db.session.commit()
            return jsonify({
                'message': '评论删除成功',
                'deleted_comment_id': action_id  # 返回前端使用的ID
            }), 200
        except Exception as e:
            db.session.rollback()
            return jsonify({'error': str(e)}), 500
        
     # ----------------- 管理员删除评论-----------------
@app.route('/admin/comments/<int:action_id>', methods=['DELETE'])
def admin_delete_comment(action_id):
    try:
        # 临时使用硬编码管理员ID（后面再换）
        TEMP_ADMIN_ID = 1
        
        # 查询评论是否存在
        comment = UserAction.query.filter_by(
            action_id=action_id,
            action_type='comment'
        ).first()
        if not comment:
            return jsonify({'error': '评论不存在'}), 404

        # 删除评论
        db.session.delete(comment)

        # 更新图片评论计数
        image = Image.query.get(comment.image_id)
        if image:
            current_count = image.comment_time or 0
            if current_count > 0:
                image.comment_time = current_count - 1

        # 记录管理员操作（使用现有admin_action_db）
        admin_action = AdminAction(
            admin_id=TEMP_ADMIN_ID,  # 硬编码管理员ID
            admin_operation='delete',
            operation_content=f"Deleted comment {action_id}"
        )
        db.session.add(admin_action)

        db.session.commit()
        
        return jsonify({
            'message': '评论删除成功',
            'admin_id': TEMP_ADMIN_ID,
            'deleted_comment_id': action_id
        }), 200
        
    except Exception as e:
        db.session.rollback()
        return jsonify({'error': str(e)}), 500

# ----------------- 点赞模块 -----------------
@app.route('/like', methods=['POST', 'DELETE'])
@token_required
def like_management():
    """点赞/取消点赞接口"""
    user = request.user
    data = request.json
    
    # 参数校验
    if 'image_id' not in data:
        return jsonify({'error': '需要image_id参数'}), 400
    image_id = data['image_id']
    
    # 验证图片是否存在
    image = Image.query.get(image_id)
    if not image:
        return jsonify({'error': '图片不存在'}), 404

    # 查询现有点赞记录
    existing_like = UserAction.query.filter_by(
        user_id=user.user_id,
        image_id=image_id,
        action_type='like'
    ).first()

    try:
        if request.method == 'POST':
            # 创建点赞记录
            if existing_like:
                return jsonify({'error': '不可重复点赞'}), 409
                
            new_like = UserAction(
                user_id=user.user_id,
                action_type='like',
                image_id=image_id,
                create_at=datetime.now()
            )
            db.session.add(new_like)
            
            # 更新点赞计数
            image.beliked = (image.beliked or 0) + 1
            db.session.add(image)
            
            db.session.commit()
            return jsonify({'message': '点赞成功'}), 201

        elif request.method == 'DELETE':
            # 删除点赞记录
            if not existing_like:
                return jsonify({'error': '未找到点赞记录'}), 404
                
            db.session.delete(existing_like)
            
            # 更新点赞计数（确保不低于0）
            if image.beliked > 0:
                image.beliked -= 1
            db.session.add(image)
            
            db.session.commit()
            return jsonify({'message': '取消点赞成功'}), 200

    except Exception as e:
        db.session.rollback()
        return jsonify({'error': f'操作失败: {str(e)}'}), 500

@app.route('/likes', methods=['GET'])
@token_required
def get_user_likes():
    """获取用户所有点赞的图片信息"""
    user = request.user
    
    try:
        
        latest_version_subq = db.session.query(
            ImageVersion.image_id,
            db.func.max(ImageVersion.upload_at).label('latest_upload')
        ).group_by(ImageVersion.image_id).subquery(name='latest_versions')

        # 主查询：关联点赞记录、图片信息、最新版本
        likes = db.session.query(
            Image.image_id,
            Image.image_title,
            Image.image_description,
            Image.midjourney_code,
            Image.beliked,
            ImageVersion.oss_path,
            UserAction.create_at  # 
        ).join(
            UserAction, 
            (UserAction.image_id == Image.image_id) &
            (UserAction.action_type == 'like')
        ).join(
            latest_version_subq,
            Image.image_id == latest_version_subq.c.image_id
        ).join(
            ImageVersion,
            (ImageVersion.image_id == latest_version_subq.c.image_id) &
            (ImageVersion.upload_at == latest_version_subq.c.latest_upload)
        ).filter(
            UserAction.user_id == user.user_id
        ).order_by(UserAction.create_at.desc()).all()

        return jsonify([{
            'image_id': l.image_id,
            'title': l.image_title,
            'description': l.image_description,
            'midjourney_code': l.midjourney_code,
            'likes': l.beliked,
            'oss_path': f'https://mjseed-code-image.oss-cn-beijing.aliyuncs.com{mj_path}'
                        if (mj_path := l.oss_path.split('mjseed-code-image', 1)[-1])
                            else l.oss_path,
            'liked_time': l.create_at.isoformat()  
        } for l in likes]), 200

    except Exception as e:
        app.logger.error(f"获取点赞列表失败: {str(e)}")
        return jsonify({'error': '获取数据失败'}), 500



# 管理员相关的路由  LJH

# 查看所有照片信息
@app.route('/admin/images', methods=['GET'])
@admin_required
def get_all_images_route():
    return get_all_images()


#查询全部oss照片的返回都是文件名
# @app.route('/admin/images/list', methods=['GET'])
# @admin_required
# def list_oss_files():
#     try:
#         result = bucket.list_objects()
#         files = [item.key for item in result.object_list]
#         return jsonify({'files': files}), 200
#     except Exception as e:
#         return jsonify({'error': str(e)}), 500


#   上传照片
@app.route('/admin/images/upload', methods=['POST'])
@admin_required
def upload_image_route():
    return upload_image()

#   删除照片
@app.route('/admin/images/<image_id>', methods=['DELETE'])
@admin_required
def delete_image_route(image_id):
    return delete_image(image_id)

#   更新照片
@app.route('/admin/images/<image_id>', methods=['PUT'])
@admin_required
def update_image_route(image_id):
    return update_image(image_id)

#   查询照片（id）
@app.route('/image/<int:image_id>', methods=['GET'])
def get_image(image_id):
    return get_image_by_id(image_id)

#   管理员查看自己发布的照片
@app.route('/admin/images/<int:admin_id>', methods=['GET'])
@admin_required
def handle_admin_images(admin_id):
    return get_images_by_admin(admin_id)




#   删除单个用户信息
app.add_url_rule('/admin/users/<int:user_id>', view_func=delete_user, methods=['DELETE'])

#   修改单个用户信息
app.add_url_rule('/admin/users/<int:user_id>', view_func=update_user, methods=['PUT'])

#   获取全部用户信息
app.add_url_rule('/admin/users', view_func=get_all_users, methods=['GET'])

#   查看单个用户信息
app.add_url_rule('/admin/users/<int:user_id>', view_func=get_single_user, methods=['GET'])

#   可以通过user_id、user_name、phone_number其中一个查询到单一用户信息
app.add_url_rule('/admin/query_user', view_func=query_user, methods=['GET'])

#   VIP充值续费
@app.route('/vip/renew', methods=['POST'])
def renew_vip():
    """
    VIP续费接口（支持套餐类型）
    Request JSON示例:
    {
        "user_id": 123,
        "payment_id": "PAY123",
        "package_type": "monthly",  # 新增参数
        "use_discount": false       # 是否使用折扣（预留字段）
    }
    """
    data = request.json
    required_fields = ['user_id', 'payment_id', 'package_type']
    if not all(field in data for field in required_fields):
        return jsonify({'error': '缺少必要参数'}), 400

    # 调用服务层
    result, status_code = renew_vip_service(
        user_id=data['user_id'],
        payment_id=data['payment_id'],
        package_type=data['package_type'],
        use_discount=data.get('use_discount', False)  # 预留折扣字段
    )
    return jsonify(result), status_code

# VIP套餐管理
app.add_url_rule('/admin/vip-packages', view_func=get_vip_packages, methods=['GET'])
app.add_url_rule('/admin/vip-packages', view_func=update_vip_package, methods=['POST', 'PUT'])
app.add_url_rule('/admin/vip-packages/<int:package_id>', view_func=delete_vip_package, methods=['DELETE'])


#对管理员的增删改查
app.add_url_rule('/admin/admins', view_func=create_admin, methods=['POST'])
app.add_url_rule('/admin/admins/<admin_id>', view_func=delete_admin, methods=['DELETE'])
app.add_url_rule('/admin/admins/<admin_id>', view_func=update_admin, methods=['PUT'])
app.add_url_rule('/admin/admins', view_func=get_admins, methods=['GET'])
app.add_url_rule('/admin/query', view_func=query_admin, methods=['GET'])





@app.route('/upload', methods=['POST'])
def upload_file():
    # 获取前端传来的文件
    file = request.files['file']
    if file:
        # 直接将文件上传到 OSS
        bucket.put_object(file.filename, file)
        return '上传成功'
    else:
        return '上传失败'

















if __name__ == '__main__':
    with app.app_context():
        db.create_all()  # 根据模型创建新表
    app.run(host='0.0.0.0', port=5000, debug=True)